const WebSocket = require("ws");
const { VisualltcModel } = require("./model/visual");

// 创建 WebSocket 服务器，监听 3005 端口
const wss = new WebSocket.Server({ port: 3005 });

// 存储所有连接的客户端
const clients = new Set();

const HEARTBEAT_INTERVAL = 5000; // 5秒发送一次ping
const HEARTBEAT_TIMEOUT = 15000; // 15秒没收到pong断开
const lastPongTime = new Map(); // 存储每个客户端上次pong时间

//重连次数
let reconnectCount = 0;

// 数据推送计数器
let pushCount = 0;

// 存储上一次的数据，用于比较变化
let lastData = null;

// 从MongoDB获取数据的函数
async function getMongoData() {
  try {
    const data = await VisualltcModel.find({});
    return data;
  } catch (error) {
    console.error("获取MongoDB数据失败:", error);
    return null;
  }
}

// 检查数据是否发生变化
function hasDataChanged(newData) {
  if (!lastData) return true;

  // 简单的JSON比较，实际项目中可能需要更复杂的比较逻辑
  return JSON.stringify(newData) !== JSON.stringify(lastData);
}

// 向所有客户端推送数据
function broadcastData(data) {
  pushCount++;
  const message = {
    type: "data_update",
    pushCount: pushCount,
    timestamp: new Date().toISOString(),
    data: data,
  };

  // console.log(`第${pushCount}次数据推送:`, data);

  clients.forEach((client) => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(JSON.stringify(message));
    }
  });
}

// 定期检查数据变化
async function checkDataChanges() {
  const currentData = await getMongoData();

  if (currentData && hasDataChanged(currentData)) {
    lastData = currentData;
    broadcastData(currentData);
  }
}

// 当有新客户端连接时
wss.on("connection", async (ws) => {
  console.log("新客户端已连接");
  clients.add(ws);

  // 立即获取并发送当前数据
  const currentData = await getMongoData();
  ws.send(
    JSON.stringify({
      type: "welcome",
      message: "欢迎连接到实时数据服务器",
      data: currentData,
    })
  );

  // 初始化心跳时间
  lastPongTime.set(ws, Date.now());

  // 定时发送自定义ping
  const pingIntervalId = setInterval(() => {
    if (ws.readyState === WebSocket.OPEN) {
      console.log("发送ping");

      ws.send(JSON.stringify({ type: "ping" }));
    }
  }, HEARTBEAT_INTERVAL);

  // 检查心跳超时
  const timeoutCheckId = setInterval(() => {
    if (ws.readyState !== WebSocket.OPEN) return;
    const last = lastPongTime.get(ws) || 0;
    if (Date.now() - last > HEARTBEAT_TIMEOUT) {
      console.log("客户端心跳超时，关闭连接");
      // ws.terminate();
      ws.close();
      clearInterval(pingIntervalId);
      clearInterval(timeoutCheckId);
      lastPongTime.delete(ws);
      clients.delete(ws);
      
    }
  }, 1000);

  ws.on("close", () => {
    console.log("客户端已断开连接");
    clearInterval(pingIntervalId);
    clearInterval(timeoutCheckId);
    lastPongTime.delete(ws);
    clients.delete(ws);
  });

  ws.on("message", (message) => {
    try {
      const msg = JSON.parse(message);
      if (msg.type === "pong") {
        lastPongTime.set(ws, Date.now());
        console.log("收到客户端pong");
        return;
      }
    } catch (e) {}
    // 其他消息
    console.log(`收到客户端消息: ${message}`);
    if (message === "ping") {
      ws.send(
        JSON.stringify({ type: "pong", timestamp: new Date().toISOString() })
      );
    }
  });
});

// 每5秒检查一次数据变化
setInterval(checkDataChanges, 5000);

console.log("WebSocket服务器已启动，监听端口 3005...");
